#!/usr/local/bin/python
# -*- coding: utf-8 -*-

import datetime
from flask import Flask, url_for, request, session, render_template, redirect
from flaskext.sqlalchemy import SQLAlchemy
from json import dumps

from bompy import app
from utils import q, table, login_required, get2parameters, formtable, textinput, unitoptions, designoptions, typeoptions
from model import Design, BOM, Production_Capacity, Production_Week, Receipt_Order, Order, Extern_Capacity

db = SQLAlchemy(app)


@app.route('/loadproduction')
@login_required
def loadproduction():
    form = (
    ("File", """<input type="file" name="PR">"""),
    )
    f=formtable(form, action="_production_db",attr=["""enctype="multipart/form-data" """, """method = "post" """])
    return render_template("loadproduction.html", f=f)


@app.route('/viewproduction')
@login_required
def viewproduction():
    tb=[]
    for i in Receipt_Order.listProducts():
        tb.append(Design.getCurrent(i).Description_Std)
    t=table(["Year ","Week "]+tb)
    return render_template("viewproduction.html",t=t)


@app.route('/_production_search')
@login_required
def production_search():
    d={"aaData":[]}
    for i in Production_Week.listWeeks():
        l=[i[0],i[1]]
        for j in Receipt_Order.listProducts():#TODO: esto solo funciona si hay una sola linea de produccion por producto
            q = Production_Week.query.filter_by(Year=i[0], Week_ISO=i[1], ID_Design=j).first()
            if q:
                l.append(q.Quantity)
            else:
                l.append("")
        d["aaData"].append(l)
    return dumps(d)    


@app.route('/_production_db', methods=['GET','POST'])
@login_required
def production_db():
    if request.method != 'POST':
        return redirect(url_for("start_screen"))
    ##############read uploaded file
    f = request.files['PR']
    s = f.readline()
    if not s[:5]=="REQ01":
        return "bad file type (no REQ01)"
    week = s[5:7]
    s = f.readline()
    l = []
    while s[:5]!="REQZZ":
        s = " "+s
        l.append([
        s[1:7], #client ID
        s[7:15], #Design ID
        s[15:19], # number by week 1
        s[19:23], 
        s[23:27],
        s[27:31],
        s[31:35],
        s[35:39],
        s[39:43],
        s[43:47]
        ])
        s = f.readline()
    lines = s[5:11]
    if int(lines)!=len(l):
        return "wrong number of lines"
    #################Load file in database
    for i in l:
        RO=Receipt_Order()
        RO.Week_Number = datetime.datetime.now().isocalendar()[1]
        RO.Code_Client = i[0]
        RO.ID_Design = i[1]
        RO.Week_4_1 = i[2]
        RO.Week_4_2 = i[3]
        RO.Week_4_3 = i[4]
        RO.Week_4_4 = i[5]
        RO.Week_4_5 = i[6]
        RO.Week_4_6 = i[7]
        RO.Week_4_7 = i[8]
        RO.Week_4_8 = i[9]
        RO.Processed = 0
        db.session.add(RO)
        db.session.commit()
    ####################Calculate production by weeks
    now = datetime.datetime.now()
    products = set()
    for i in Receipt_Order.query.all():
        products.add(i.ID_Design)
    
    for p in products:
        qu=0
        for i in Receipt_Order.query.filter_by(ID_Design=p,Processed=0):
            qu+=i.Week_4_1
            qu+=i.Week_4_2
            qu+=i.Week_4_3
            qu+=i.Week_4_4
            qu+=i.Week_4_5
            qu+=i.Week_4_6
            qu+=i.Week_4_7
            qu+=i.Week_4_8
        for i in range(5,105):
            if qu>0:
                #print qu,
                d = now + datetime.timedelta(weeks=i)
                week = d.isocalendar()[1]
                year = d.isocalendar()[0]
                Pold = Production_Week.query.filter_by(ID_Design=p,Year=year,Week_ISO=week).first()
                if Pold:
                    cap = Production_Capacity.query.filter_by(ID_Line=Pold.ID_Line).first().Capacity
                    if Pold.Quantity == cap:
                        pass
                    elif Pold.Quantity < cap:
                        if (Pold.Quantity + qu) <= cap:
                            old = Pold.Quantity
                            Pold.Quantity = Pold.Quantity + qu
                            qu = qu -(can-old)
                            db.session.merge(Pold)
                            db.session.commit()
                        else:
                            qu = qu-(cap-Pold.Quantity)
                            Pold.Quantity=cap
                            db.session.merge(Pold)
                            db.session.commit()
                      
                else:
                    PW = Production_Week()
                    d = now + datetime.timedelta(weeks=i)
                    PW.Week_ISO = week
                    PW.Year = year
                    PW.ID_Design = p
                    PW.ID_Line = Production_Capacity.query.filter_by(ID_Design=p).first().ID_Line
                    PW.Quantity = 0
                    PW.Processed = 0
                    PW.Start_Date=datetime.datetime.now()
                    PW.User_Create=1
                    cap = Production_Capacity.query.filter_by(ID_Line=PW.ID_Line).first().Capacity
                    if qu>cap:
                        qu-=cap
                        PW.Quantity=cap
                        db.session.add(PW)
                        db.session.commit()
                    if qu<=cap:
                        PW.Quantity=qu
                        qu=0
                        db.session.add(PW)
                        db.session.commit()
    ####################Do orders
    print "empezar orden"
    #TODO no anda nada, mucho lio de dicts anidados
    orders={}
    for i in Production_Week.query.all():
        if not i.Processed:
            for j in Design.getCurrent(i.ID_Design).explode():
                if j[0].ID_Design_Type == 2:#tipo buy
                    if not orders.has_key((i.Year,i.Week_ISO)):
                        orders[(i.Year,i.Week_ISO)]={}
##                        print "creando1"
                    if not orders[(i.Year,i.Week_ISO)].has_key(j[0]):
                        orders[(i.Year,i.Week_ISO)][j[0].ID_Design]=j[1]*i.Quantity
##                        print "creando2"
                    else:
                        orders[(i.Year,i.Week_ISO)][j[0].ID_Design]+=j[1]*i.Quantity
##                        print "sumando"
#    print "empezar loop orden"
    for i in orders:
        for j in orders[i]: #TODO: use ExternCapacity
            print "loopear orden"
            ID = j
            QU = orders[i][j]
            ecs = Extern_Capacity.listExterns(ID)
            if not ecs:
                return "falta proveedor: "+ ID
            order = Order()
            order.User_Create = 1
            order.Start_Date = datetime.datetime.now()
            order.ID_Extern = ecs[0].ID_Extern
            t = iso_to_gregorian(i[0],i[1],1)
            t = t - datetime.timedelta(weeks=ecs[0].Time)
            order.Year = t.isocalendar()[0]
            order.Week_ISO = t.isocalendar()[1]
            order.ID_Design = ID

 
            if len(ecs)>1:#Poner 70% al mas barato, 30% al segundo, y despues el resto al mas barato, y al final al mas caro
                order2 = Order()
                order2.User_Create = 1
                order2.Start_Date = datetime.datetime.now()
                order2.ID_Extern = ecs[1].ID_Extern
                t = iso_to_gregorian(i[0],i[1],1)
                t = t - datetime.timedelta(weeks=ecs[1].Time)
                order2.Year = t.isocalendar()[0]
                order2.Week_ISO = t.isocalendar()[1]
                order2.ID_Design = ID
                primero = ecs[0]
                segundo = ecs[1]
                cantidad = QU
                cappri = primero.Capacity
                capseg = segundo.Capacity                        
                if cantidad <= (cappri*0.7): #poner todo en primero
                    Order.Quantity = cantidad
                    db.session.add(order)
                    db.session.commit()
                elif cantidad <= ((cappri * 0.7) + (capseg * 0.3)): #poner en primero y segundo
                    part = int(cappri*0.7)
                    order.Quantity = part
                    order2.Quantity = cantidad - part
                    db.session.add(order)
                    db.session.add(order)
                    db.session.commit()
                    
                elif cantidad <= (cappri + (capseg * 0.3)):
                    part = int(capseg * 0.3)
                    order.Quantity = cantidad - part
                    order2.Quantity = part
                    db.session.add(order)
                    db.session.add(order)
                    db.session.commit()
                
                else:
                    order.Quantity = cappri
                    order2.Quantity = cantidad - cappri
                    db.session.add(order)
                    db.session.add(order)
                    db.session.commit()
                
            else:#Poner todo en el unico
                order.Quantity = QU
                db.session.add(order)
                db.session.commit()
                
    for i in Receipt_Order.query.all():
        i.Processed = 1
        db.session.merge(i)
        db.session.commit()
    
    for i in Production_Week.query.all():
        i.Processed = 1
        db.session.merge(i)
        db.session.commit()
    
    return redirect(url_for('viewproduction'))
    

def iso_year_start(iso_year):
    "The gregorian calendar date of the first day of the given ISO year"
    fourth_jan = datetime.date(iso_year, 1, 4)
    delta = datetime.timedelta(fourth_jan.isoweekday()-1)
    return fourth_jan - delta 

def iso_to_gregorian(iso_year, iso_week, iso_day):
    "Gregorian calendar date for the given ISO year, week and day"
    year_start = iso_year_start(iso_year)
    return year_start + datetime.timedelta(days=iso_day-1, weeks=iso_week-1)



